﻿using System;
using GameCreator.Camera;
using Gp.Input;
using Gp.Scripts.GameLogic;
using Gp.Scripts.GUI;
using QFramework;
using Sirenix.OdinInspector;
using UnityEngine;

namespace Gp.Scripts.Core {
    public class ChangeHotSpotEvent {
        public Transform HotSpot;
        public object Key;
        public ChangeHotSpotEvent(Transform hotSpot) {
            HotSpot = hotSpot;
            Key = HotSpot;
        }

        public ChangeHotSpotEvent(Transform hotSpot, object key) {
            HotSpot = hotSpot;
            Key = key;
        }
    }

    public class ResetHotSpotEvent {
        public object Key;
        public ResetHotSpotEvent(object hotSpot) {
            Key = hotSpot;
        }
    }
    
    
    
    
    public class CameraFlowPivot : MonoBehaviour {
        [Title("鼠标偏移")]
        [SerializeField] private float maxOffset = 1;
        [Range(0, 1)] [SerializeField] private float hotSpotWeight = .5f;
        [SerializeField] private Vector2 mouseOffset = new (2, .5f);
        [Title("角色视角参数")]
        [LabelText("常态视角")]
        [SerializeField] public Vector3 normalView = new Vector3(0, 12, -8); 
        [LabelText("聚焦视角")]
        [SerializeField] public Vector3 focusView = new Vector3(0, 10, -4);
        [LabelText("视角改变速度")]
        [MinValue(0.2)]
        [SerializeField] private float motorMoveSpeed = 6;
        
        private Vector3 _targetMotorOffset; 
        
        private GameArea CurArea { get; set; }
        public Transform HotSpot;
        public Transform MainFollowTarget;
        
        private object _key;
        

        private void Start()
        {
            this._targetMotorOffset = normalView;
            // this.RegisterEvent<PlayerEnterAreaEvent>(OnAreaEnter);
            // this.RegisterEvent<PlayerExitAreaEvent>(OnExitArea);
            Global.RegisterEvent<ChangeHotSpotEvent>(args => {
                HotSpot = args.HotSpot;
                _key = args.Key;
            });
            
            Global.RegisterEvent<ResetHotSpotEvent>(args => {
                if (_key == null || args.Key == _key ) {
                    HotSpot = null;
                }
            });
        }
        

        private void Update() {
            if (MainFollowTarget == null) return;
            if (Global.GetSceneRoot<PlayerRoot>().MainCameraMotor.cameraMotorType is CameraMotorTypeFollow follow) {
                // 将摄像机降低
                follow.anchorOffset = Vector3.Lerp(follow.anchorOffset, _targetMotorOffset, motorMoveSpeed * Time.deltaTime);
            }
            
            var pivotPos = MainFollowTarget.transform.position;
            pivotPos = ProcessHotSpot(pivotPos);
            if (Global.Get<InputManager>().IsMousePressing(MouseButtonCode.MouseRightButton)) {
                pivotPos = ProcessMouseOffset(pivotPos);
            } 

            transform.position = ClampPos(pivotPos);
        }
        

        private Vector3 ProcessHotSpot(Vector3 mainTargetPos) {
            if (HotSpot == null) return mainTargetPos;
            var delta = HotSpot.transform.position.x - mainTargetPos.x;


            delta *= hotSpotWeight;
            delta = Mathf.Clamp(delta, -maxOffset, maxOffset);
            mainTargetPos.x += delta;
            
            return mainTargetPos;
        }

        
        private Vector3 ProcessMouseOffset(Vector3 pivotPos) {
            var mousePos = Global.Get<InputManager>().MousePosition();
            var posX = Mathf.Pow(mousePos.x / Screen.width, 2) - .5f;
            
            var posY = Mathf.Pow(mousePos.y / Screen.width, 2) / Screen.height - .5f;
            var deltaX = mouseOffset.x * posX;
            deltaX = Math.Clamp(deltaX, -1f, 1f);

            posY = mouseOffset.y * posY;
            posY = Math.Clamp(posY, -.2f, .2f);
            
            pivotPos.x += deltaX;
            pivotPos.z += posY;
            
            return pivotPos;
        }

        
        private Vector3 ClampPos(Vector3 mainTargetPos) {
            if (CurArea == null) return mainTargetPos;
            var border = CurArea.GetBorder();
            // border -= boundsFix;

            // float len = border.y - border.x;

            float clamp = Mathf.Clamp(mainTargetPos.x, border.x, border.y);
            mainTargetPos.x = clamp;
            return mainTargetPos;
        }

        public void SetFocusMode(bool flag)
        {
            this._targetMotorOffset = flag ? this.focusView : this.normalView;
        }
    }
}